iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Software Development

MongoDB披荊斬棘之路系列 第 7

DAY7 MongoDB 資料更新(Update)

  • 分享至 

  • xImage
  •  

DAY7 MongoDB 資料更新(Update)

更新(update)

資料更新(Update)如同寫入或刪除一樣,都是相同 Pattern,差別是條件比較多。

db.collection.updateOne(filter, update, options)
db.collection.updateMany(filter, update, options)

兩者基本上是一樣的,相信你們看完前面的 insertOne, insertMany, deleteOne, deleteMany 都有感覺了。

filter 是過慮條件,也就是你要找到欲更新文件的條件。

options 這個是更新的設定選項,在剛開始會用不到太多項目,只有一個要特別注意,就是 upsert,通常我們會設定為 true,這也是 MongoDB 很方便的地方。顧名思義,就是當欲更新的文件如果存在時,進行 update,當找不到這比文件時,就進行 insert

UpdateOne Demo - 1

馬上來個範例,我們先查詢,確保沒有該文件,接著執行 upsert:trueupdateOne 語法:

film> db.upsert.sample.find()

film> db.upsert.sample.updateOne({},{$set:{'name':'try upsert'}},{upsert:true})
{
  acknowledged: true,
  insertedId: ObjectId("6131047cf80a26301f6a5856"),
  matchedCount: 0,
  modifiedCount: 0,
  upsertedCount: 1
}
film> db.upsert.sample.find()
[ { _id: ObjectId("6131047cf80a26301f6a5856"), name: 'try upsert' } ]
film>

可以看到 upsert.sample collection 起初是沒有資料的,我使用了 find(),不帶任何參數的查詢,查不到任何資料。
接著再一個 updateOne 的內容裡,執行後直接新增比資料,透過回傳的參數也可以看到 upsertedCount 數量為 1。

  • insertedId:本次執行結果,寫入的 ObjectId 清單
  • matchedCount:本次執行結果,符合查詢條件的文件數量
  • modifiedCount:本次執行結果,符合查詢條件且更新的文件數量
  • upsertedCount:本次執行結果,進行 upsert 的文件數量

接著將這次的 updateOne 語法來拆開來看:

db.upsert.sample.updateOne(
{},
{$set:{'name':'try upsert'}},
{upsert:true}
)

可以看到三組大括弧 {},這分別對應了上面提到的 filter, updateoptions

  • filter:這邊我們直接不帶條件,想進行全部文件的 update
  • update:我們設定 name 欄位的值為 try upsert,$set 是 MongoDB 的 operator 之一,這個我們之後再講解,先忍著略過它。
  • options:這次 updateOne 中,設定值設定 upserttrue,代表找不到資料就寫入。設定還有 writeConcern, collationhint 等,這個會在後面再講解,現在提就太深入了。

UpdateOne Demo - 2

這次我們準備幾筆符合查詢條件的文件,使用 UpdateOne 看看會發生什麼事情。

資料庫內有三筆名為 Arthas 的資料

film> db.upsert.demo2.find()
[
  { _id: ObjectId("61310798630faf5d23c909d3"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d6"), name: 'Thrall' }
]

執行 updateOne,將名為 Arthas 的資料欄位改為 ErrorName

film> db.upsert.demo2.updateOne({'name':'Arthas'}, {$set:{'name':'ErrorName'}})
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
film> db.upsert.demo2.find()
[
  { _id: ObjectId("61310798630faf5d23c909d3"), name: 'ErrorName' },
  { _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d6"), name: 'Thrall' }
]

可以看到執行後,再次查詢,只會有第一筆被修改,因為我們執行的是 updateOne

那為什麼第一筆不是_id9d49d5 結尾的資料呢?因為 MongoDB 採用的是 natural sort,在這個情況下就是 9d3 這一筆。我們會在後面的天數講到 natural sort,這是一個非重要的概念。

replaceOne

replaceOne,找到符合條件的文件,直接整份文件取代。

replaceOne 用法與 Update 高度相近,來看看它的長相:

db.collection.replaceOne(filter, replacement, options)

  • filter: 設定的查找文件條件
  • replacement: 新的文件內容
  • options: 設定值,與 update 的幾乎一樣。

我們來嘗試找到一個文件,{name:'Thrall'},將它改成下面這樣子

{
    'name':'NewThrall', 
    'type':'melee'
}    
film> db.upsert.demo2.find()
[
  { _id: ObjectId("61310798630faf5d23c909d3"), name: 'ErrorName' },
  { _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d6"), name: 'Thrall' }
]
film> db.upsert.demo2.replaceOne({'name':'Thrall'}, {'name':'NewThrall', 'type':'melee'})
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
film> db.upsert.demo2.find()
[
  { _id: ObjectId("61310798630faf5d23c909d3"), name: 'ErrorName' },
  { _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
  { _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
  {
    _id: ObjectId("61310798630faf5d23c909d6"),
    name: 'NewThrall',
    type: 'melee'
  }
]

可以看到新的內容已經取代上去,特別要注意的是 _id 並沒有任何異動,即便它不是客製化的 _id,仍然不會改變,因為這個操作是取代文件內容,不會影響它本身的 key。

附帶一提,replaceOne 如同上面所說,設定值是幾乎一樣的,所以也有 upsert 功能,這邊就不再示範了,結果會與 update 一樣。


本系列文章會同步發表於我個人的部落格 Pie Note


上一篇
DAY6 MongoDB 資料新增(Insert) 與刪除(Delete)
下一篇
DAY8 MongoDB 批次操作(bulk wirte) 與 Operators
系列文
MongoDB披荊斬棘之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言